Transforming Speciications of Observable Behaviour into Programs 1

نویسندگان

  • David Gilbert
  • Christopher Hogger
چکیده

A methodology for deriving programs from speci cations of observable behaviour is described. The class of processes to which this methodology is applicable includes those whose state changes are fully de nable by labelled transition systems, for example communicating processes without internal state changes. A logic program representation of such labelled transition systems is proposed, interpreters based on path searching techniques are de ned, and the use of partial evaluation techniques to derive the executable programs is described. 1 Motivations Our methodology provides a means for deriving executable programs from speci cations of the observable behaviour of a restricted class of systems. The systems which are tractable by this methodology are those whose observations are discrete ne-grained steps which progressively construct data objects, expressed as terms in our approach. We give the characterisation of these systems by the use of a language based on labelled transition systems, and identify a class of interpreters derived from rewriting and path searching algorithms on the graphs induced by the labelled transition systems. Furthermore, we are able to derive programs by partially evaluating such interpreters with respect to the rules in the language of the labelled transition systems. We also provide a formalism which permits the transformation of the labelled transition systems into the target programs within the framework of computational logic. The class of computations in which we are interested contains those whose result is incrementally constructed, whilst at the same time the partial results are being output as observations which are accessible to the environment of the computing agent. For some of these computations it is natural also to specify such processes in terms of their observable behaviour. We believe this may be closer to the user's understanding of the system to be programmed, when the external behaviour of the system and the sequence in which the result is produced (i.e. a trace history) is an essential part of the activity of the process. For the sake of simplicity, we assume that the observation of the external behaviour is tightly linked to the internal computation steps of such a system, i.e. each step of the computation strictly extends the resulting data structure which it constructs. Our method regards observations of the progress of a computation as extrinsic speci cations which can be represented as directed acyclic graphs. Each computation that the system can perform is represented by a path through the graph, which in turn can be described in rst order logic. Logic programs can be derived from these rst order logic descriptions by standard transformations. We view the long-term objective of our method to be the construction of reactive concurrent systems. As a rst step towards this objective we present a working framework for sequential systems. From a more abstract point of view, we can understand the procedure for constructing programs from graphs representing observable behaviour as a compiler of a graph-based production language. A particular strategy for the generation of computations from such a graph can be linked to the particular strategy for the search of the tree representing the trace history of the execution of the corresponding program. In general, the method as presented in this paper makes no assumptions about the sequential or concurrent behaviour of the programs which have been generated; such behaviour is a result of the execution mechanism for these programs. 2 Summary of the Approach The outline of our approach can be given as follows: rst, give a speci cation of all the possible sequences of the observable behaviour of the system to be constructed. This is done by determining the elementary transitions between the states of the program which produce the observables, and taking these transitions as a de nition of a labelled transition system which can generate all the possible state changes. Since we assume that every change of state of a program is immediately re ected in production of an observable (i.e. an output visible to the external observer), we identify internal states with their associated observations. Second, take a general interpreter of the resulting labelled transition system expressed in a suitable language. This interpreter is a path searching algorithm which explores the graph of transitions generated by the system. The structure of observations, labelled transitions, and the path searching procedure can all be formalised in the language of rst-order Horn clause logic. Labels of the initial transformation system are identi ed with suitable variables, and partial objects built as a result of partial execution of the program. These objects can be identi ed with terms containing variables in places at which the structure will be later extended during further program execution. Within the language of logic, generation of a particular 2 observable corresponds to substituting the term representing this observable for the free variable at the location where the new observable occurs. Hence the term which is being constructed during a program run corresponds to a tree of a particular history of observable state transitions, represented as a term. When specifying path-searching procedures working over the state space of a particular labelled transition system represented in logic, substitution plays the the rôle of the basic operation performed. Each transition of the initial labelled transition system thus corresponds to an atomic substitution, and sequences of transitions correspond to compositions of atomic substitutions of this kind. Based on this, the path-searching procedure works over compositions of substitutions. Therefore the resulting program de ned by such a system amounts to a generator of substitutions. These substitutions in turn correspond to changes of program observables, i.e. to program state transitions. The substitution generator therefore works as an interpreter working over the labelled transition system. Finally, generate a program which implements the labelled transition system by partially interpreting the path searching algorithm applied to the set of transition rules. We employ a partial evaluator for logic programs for this and hence use logic programming for all three steps. The scheme outlined above depends on the feasibility of realising each of the steps involved so that the goal of generating the program from the speci cation can in fact be achieved. In this paper we describe a particular formal framework which permits this goal to be accomplished. We start with a simple de nition of a labelled transition system de ned as a system for synchronously rewriting several labels during one transition step. The intuitive meaning of this de nition is that several processing agents can act synchronously within the computational environment. We then embed these systems into clauses de ning transitions of the system. From this point on, all of the construction is performed in a logic programming language, Prolog in our test implementation, starting from data structures, path-searching algorithms and generation of state-change histories i.e. terms generated by subsequent applications of substitutions corresponding to observable changes. The partial interpretation needed is therefore just a general logic programming partial interpreter (Mixtus [21] in our case). Within each of the steps we discuss the data structures involved and the simpli cations which can be employed. Note that because of the metaprogramming features of our approach which is based on a path-searching interpreter, we need to specify substitutions as operations at the meta-level, 3 rather than to rely on substitutions performed by the underlying engine of the logic programming language used for implementation. If the method is to be practically usable, the implementation of the manipulation of substitutions has to be substantially simpli ed in order that the generation of the nal programs by partial evaluation terminates. Special discussion is therefore devoted to using the general properties of the substitutions which can possibly occur during the process of path generation, and to designing a modi ed de nition of substitution suitable for this step. 3 Specifying Observable Changes We use a labelled transition system (LTS) to describe possible changes of observables in the system. Such a system is given by a set of transition rules of the form (x1; : : : ; xn) 7! (t1; : : : ; tn) where n 1 Note that we permit more than one label on the left-hand side of the transition, enabling us to describe systems where more than one observables may change concurrently. x1; : : : ; xn are the labels, or identi ers representing observables, and t1; : : : ; tn are general expressions built over the labels and other atoms. These latter denote the resulting con guration after observable change, and may include the observable identi ers again as a proper subpart of any of them. The expressions on the right-hand side correspond to fragments of the trees (terms) of trace histories associated with observable data generation. An example of a labelled transition rule which describes the generation of a list is (x) 7! (a:x) We may extend this to the description of a system which counts the number of items in a list: (x; y) 7! (a:x; succ(y)) The informal motivation is to consider the labels as states, and to take each transition rule as a de nition of a state change, possibly acting synchronously over several processes (if n > 1). The expressions on the righthand side permit the de nition of both the observable output and the resulting change of the state, including termination or splitting into several processes. One can think of the expressions generated by systems of this kind as snapshots of trace histories of processes which are represented by 4 labels. Transitions can be applied to any of those labels in order to expand the structure representing the current partial trace-history. Observables produced by the system correspond to functors (atoms) occurring in the expressions generated by the LTS. (In the logic programming representation, these will be functors of the language.) The descriptive power of the formalism is most easily understood by considering the class of processes which can be determined by a LTS as a language generated by a grammar derived from it. On an abstract level, any LTS corresponds to a grammar whose nonterminal symbols represent the labels of the LTS, and whose terminal symbols correspond to data structures. Thus the nonterminals actually correspond to states of a computation (sequential or parallel) represented by expanding the starting state. Even in the sequential case, the resulting pattern is di erent from just recursive descent due to the treatment of all the non-terminals produced in an expansion step as a partial process output. This re ects our interest in focussing primarily on generating/specifying traces of computations as sequences of process outputs, not just the resulting (data) structure given by the words generated by the grammar. If the transitions of the LTS transitions only have one label expanded at each step the resulting grammar is at most a context free grammar, with all the inherent limitations of CFGs, which for example cannot represent the concurrent update of more than one label. The treatment of the class of systems which we consider within our framework contains transition rules which can concurrently transform several labels at the same time, permitting us to describe concurrent systems, and leads to a sub-class of context grammars which is strictly larger than CFGs. 4 Target Program Structure The processes speci ed by this class of LTS can be represented in various ways, depending on the actual programming paradigm selected. In our approach, representation as a logic program is chosen, because of the declarative nature of this paradigm. This permits us to develop a framework for program synthesis which is independent of the particular implementation of the processes it de nes, either sequential or concurrent. When the resulting logic programs are coupled with a corresponding evaluation strategy, this is e ectively equivalent to a program in a procedural programming language, yet the particular level of abstraction permits a more succinct representation 5 of the problem. The observables of a logic program are the logical variables in the initial goal associated with it. Uni cation is the nest level of granularity which is useful to observe, and thus uni cation steps are taken to be the atomic events which are observable. Communication in a logic programming system occurs via bindings made to shared variables, and our assumption is that an observer can detect the incremental bindings made to the variables in the initial goal (i.e. to external variables). The observations made are posets of binding sets; we can represent these posets as directed acyclic graphs, due to the write-once nature of the logic variable. The bottom element of such a set represents the initial unbound state of the observable variables. Each path through the graph from the minimum vertex to a maximum vertex comprises the observations of one computation and the union of the sets associated with all such paths comprises the instantiation set of the observational variable(s). An example is the instantiation set of the following directed graph for the variable x. Nodes are labelled with the term to which x is bound, and an arc from node A to node B is labelled with the substitution which when applied to the term at A results in the term at B. x f(y; z) f(y; t2) f(t1; z) f(t1; t2) fx=f(y; z)g fz=t2g fy=t1g fy=t1g fz=t2g fy=t1 z=t2g 66 @ @ @ @I @ @ @ @I Fig. 1. fx=f(y; z); x=f(t1; z); x=f(t1; t2)g [ fx=f(y; z); x=f(y; t2); x=f(t1; t2)g[ fx=f(y; z); x=f(t1; t2)g = fx=f(y; z); x=f(t1; z); x=f(y; t2); x=f(t1; t2)g Given the choice of logic variables as observables, the actual data items produced by a running program are represented by the functors of the language of terms. Therefore changes of a process state are manifested by 6 assignment of data to the tuple of logic variables representing the process. The particular syntactic structure is just a consequence of our use of logic terms to represent data structures. During the transformation of terms into pre x/post x notation, the non-variable symbols in them correspond straightforwardly to terminal symbols of the grammar associated with the original LTS. The use of logic variables permits the representation of trace histories as simple variable bindings, with no additional formalism being needed. An example of an LTS is the pair of transition rules: (x) 7! (a:x) (x) 7! (nil) These rules represent an LTS which describes the behaviour of a process which binds a variable to list and whose trace history is itself a list of the binding states of that variable. There is a regular grammar corresponding to this system, X ! aX X ! characterizing the set of process behaviour as the corresponding regular set of sequences of data items a of arbitrary length. The logic-variable representation uses just one type, X , for the variables of the LTS. The tuples on the right-hand sides of the production rules can be represented by terms a(x), where x is a variable of the type X and a a unary function symbol, and by a nullary functor symbol nil, respectively. 5 Logic Program Representation When specifying a logic program, we choose to identify the observables by logic variables. As far as these correspond to distinct labels of the LTS, or distinct non-terminals of the grammar, there is a need to ensure that the correspondence of every variable with its associated label is preserved. Without such correspondence substitutions may be applied to incorrect variables. This correspondence can be achieved by partitioning the sets of labels and identi ers using tags. On the level of speci cation, we choose to work in a multi-sorted logic, where types can be used to perform this tagging function. Each variable is therefore associated with a unique xed type. All the usual properties of logic programs are preserved within this, and the only change 7 to the underlying machinery required is that of modifying uni cation so that it fails whenever an attempt to bind a variable of certain type to a term of di erent type is made. Thus, for example, in the rule (x; y) 7! (a:x; succ(y)) we consider that x and y are of di erent types. The type scheme resulting from the use of labels of the LTS as types of the system permits simple static type checking, for example that of G odel [11]. Note that with static type checking it is su cient to verify type constraints at the level of the source program code, and so at run-time it is possible to use type-less logic programming language, such as Prolog, and hence not to refer to types. In our case this corresponds to the need to ensure proper type constraints when writing the interpreter, as proposed by Hill and Lloyd [10], but the actual programs generated by partial evaluation are ordinary type-less logic programs. The idea of using typed terms is just a syntactic means for avoiding the use of dynamic predicate-based type checking. The untyped predicate logic is expressible enough to de ne all that is needed for this, but requires the use of a more complex clause structure for the representation of the transition rules. Speci cally we need to introduce predicates for dynamic type checking into each of the clauses of the interpreter. The framework of typed terms seems more natural in our context for two reasons. Firstly because of the example of the successful use of types in logic programming which has been set by G odel, and secondly because the use of types simpli es the representation of transition rules as clauses by e ectively moving the typechecking predicates out of such clauses into the code of a general-purpose interpreter. For the representation of the LTS, the left-hand side of a rule becomes a tuple of logic variables, and the right-hand side is represented by a tuple of terms containing new versions of the variables, all of the variables being typed by the appropriate LTS label types. The version of the above example would be (x; y) 7! (a:x0; succ(y0)) where x and x0 are of the same type, and so are y and y0. In order to implement the above process in Prolog, we choose a representation of variables in which each variable carries its source observable id as a type associated with it. This observable id tag controls the possible variable 8 occurrences which may or may not match with the variables resulting from a labelled transition rule. Obviously, when using a typed logic programming language such as G odel, the representation could be made simpler. Observable changes can now be described by the successive instantiation of variables, a characteristic feature being the possibility of binding variable to a term containing yet more variables. Non-linear structures can be generated in such a way, with several new observables being generated as a result, for example the generation of tree structures. Instantiations of variables are carried out by substitutions, de ned as morphisms on terms, fully described by their result on variables. In the case of nite substitutions (which only change a nite number of variables), the usual notation = [x1=t1; : : : ; xn=tn] describes a mapping de ned as t = 8<: ti if t = xi for xi=ti 2 ; t if t is a variable, not occurring as t=u 2 for any u; f(t1 ; : : : ; tn ) for t = f(t1; : : : ; tn); n 0. Substitutions de ne state-changing operations on the processes, and the program-generating process developed later in this paper is based on building a meta interpreter which combines substitutions in a suitable way. The process of observables transformation leads to the composition of substitutions de ned as function compositions. On nite substitutions this this gives the following standard de nition: = [x=t jx=t 2 and x 6= t ] [ [y=s 2 and for every t, y=t 62 ] Note that the second operand of the union allows us to eliminate those changes to variables de ned by which are ine ective because of a previous elimination of suitable variable occurences by . We will employ this fact in the following section to simplify our working de nition of composition. At this point, the LTS can be transformed into substitutions: for each rule (x1; : : : ; xn) 7! (t1; : : : ; tn) generate a set of substitutions of the form [x1=t01; : : : ; xn=t0n] with identi ers expressed as logic variables. Moreover, within each pair xi=t0i, t0i is formed from ti by renaming all variables into fresh ones. As 9 noted above, we assume the existence of typed variables, and hence the framework of a multi-sorted language. When actually implementing this operation in a language lacking strict type discipline (such as Prolog), some extra care must be taken in the actual code to ensure that the types of the variables are preserved when renaming them. Now the program speci cation part can be viewed as the set of rules describing the accumulation of substitutions: input substitution is composed with the observable-changing substitution in order that the resulting substitution is a new con guration of the system. 6 Instantiation Steps Our method describes computations as ones which progressively instantiate variables to terms. We represent terms explicitly by substitution sets, and describe the instantiation of a term t to a more specialised form t0 by the relation compose(x; y; z) where x is the substitution set associated with t z is the substitution set associated with t0 y is the substitution set whose composition with x results in z. For example, consider the following set of possible instances of a variable xfx; f(y; z); f(t1; z); f(y; t2); f(t1; t2)g which corresponds to the set of atomic substitutions illustrated by Figure 1 above. From this poset we may extract, by closure over the arcs, one of the possible binding histories, e.g. [x=f(y; z)]::[x=f(t1; z)]::[x=f(t1; t2)] which we illustrate in Figure 2 below x f(y; z) f(t1; z) f(t1; t2) fx=f(y; z)g fy=t1g fz=t2g 6 @ @ @ @I Fig. 2. 10 We can then associate the following compositions with the binding history: compose([x=f(y; z)]; [y=t1]; [x=f(t1; z); y=t1]), compose([x=f(t1; z); y=t1]; [z=t2]; [x=f(t1; t2); y=t1; z=t2]) We will need to add some restrictions to the standard de nition of substitution in order to re ne our technique. The rst is linked to our basic assumptions about the class of systems we are interested in. The acyclicity of the underlying LTS re ects the intuition that during the process of computation there is always some visible non-empty output after each step. In terms of bindings, this means that there is a progression in the binding sequence which prohibits simple renaming occurring as local instantiation steps. This permits the elimination of useless compositions such as compose([x=y]; [y=z]; [x=z; y=z]) and hence prohibits the inclusion of x=y where x and y are variables in the substitution set at the second argument of compose/3 Our top-level de nition is compose(A, B, C) progress(A, B, C) , full-compose(A, B, C) where full-compose/3 is the relation corresponding exactly to the general mathematical de nition of substitution composition without any additional restrictions. Here progress(A;B;C) means that C is not a variant of A, i.e. B must be some non-trivial binding corresponding to an observable state change. The above-outlined model is too general and contains excessive checks on the substitutions which result from composition. The checks for idempotent substitution pairs and for the elimination of variables from the standard de nition of substitution make the partial evaluation of the target program unnecessarily complicated. Pragmatically we found the de nition to be too general, and the partial evaluation did not terminate under Mixtus. The picture can be simpli ed by the consideration of the constraints result from the source LTS structure and the way substitutions are generated from it. First, variables on the right-hand side of substitution pairs can be renamed, so that xi 62 ti for any xi=ti. Also, for any xi=ti 2 there is no yi=uj 2 such that xi 2 uj for any substitution pair , , which can possibly be considered a result from composing substitution with substitution resulting from LTS. This is because variables in uj have been generated as fresh, not yet occurring elsewhere. As a result, the idempotency check can be omitted from the de nition of composition. 11 Second, in substitutions and , for any xi=ti 2 there is no yj=uj 2 such that xi = yi. Again, this is a result of state-changing substitution being generated from LTS rules. Consequently, the elimination check can be omitted as well. The resulting de nition of substitution needed for describing observable changes therefore reads as follows: = [xi=ti jxi=ti 2 ] [ : This allows us to simplify the partial-evaluation phase signi cantly (see Section 9), and to provide for a manageable program generator out of the source LTS. 7 Constraining Instantiation Steps The de nition of composition as given above is too general for our purposes and does not constrain instantiation to any particular discrete steps. The concept of expanding the underlying LTS-related grammar corresponds to performing computations using the LTS-based speci cation which leads to the identi cation of computational steps with the expansion of nonterminals, i.e. variable instantiation. Such an instantiation is limited to terms of the structure which correspond to the left-hand sides of transformation rules, i.e. such an instantiation step typically replaces variables either by constants or by trees of a restricted depth. Hence we are only interested in systems which instantiate terms in such a minimal manner, and thus introduce the notion of a (non-null) atomic substitution set Y whose application to a substitution set X by compose(X,Y,Z) satis es the following constraints: There is at least one non-ground ti of vi=ti 2 X which is further instantiated by vj=tj 2 Y (where tj is not a variable). vj=tj is minimal in some sense to the particular application We can de ne atomic/1 which is part of the meta-interpreter by: atomic(Y) lts(P 7! Q), transform(P 7! Q, Y) where lts/1 is the object level program and transform/2 performs the transformation operation from the LTS into substitutions referred to in Section 5. For example, we may take for lists the pair of transition rules represented by lts/1: 12 lts((x) 7! (a:x)) lts((x) 7! (nil)) which are transformed to [x=a:x0] and [x=nil] respectively. We now can give a de nition of a new predicate inst(X,Z) which relates a substitution set X, about a term T, to a substitution set Z, about the immediate successor T' of T, as determined by some applicable substitution set Y: inst(X,Z) atomic(Y), compose(X,Y,Z) 8 Node Traversal of Instantiation Graphs The inst/2 predicate allows us to describe only one individual step, or edge, in the instantiation graph which represents the graph of transitions, whereas we ultimately intend to describe the graph as a whole. More speci cally, having provided a de nition or program for `inst' in respect of some particular application, we want to incorporate it within some encompassing program which traverses the DAG determined by `inst'. The classic path traversal method, for example as shown by Kowalski [13] relates nodes (in this case substitution sets) to their subsequent states. Consider any node N already generated; after one or more atomic steps, various paths will have been developed to some further node N. We can de ne the following pathnding programs by the transitive closure of inst/2: Program A1 path(N, F) inst(N, F) path(N, F) inst(N, N0) , path(N0, F) inst(N, F) compose(N, Y, F) , atomic(Y) Program A2 path(N, F) inst(N, F) path(N, F) inst(N0, F) , path(N, N0) inst(N, F) compose(N, Y, F) , atomic(Y) Which program is used is determined by the input-output mode with which path/2 is queried; the entire graph can be traversed by inputting N as the bottom node and using path1 to seek all reachable nodes F, or vice-versa. We can now follow the method of Gilbert and Hogger [8] which derived path exploration programs which computed only the di erences between 13 nodes. In the context in which compose/3 appears, constrained together with atomic/1, it cannot be used in any way which would not satisfy the following conditions, as de ned by Brough and Hogger [4]: (1) (8N 8Y 9F)(compose(N,Y,F)) Some result F be de ned for any Y applied to any N. (2) (9 I 8Y 8F)(compose(I,Y,F)$ Y=F) compose to have at least one left-identity I. (3) (8N 8Y 8Y0 8F) ((compose(N,Y0,F) $ Y0=Y) compose(N,Y,F)) (8N 8Y 8F 8F0) ((compose(N,Y,F0) $ F0=F) compose(N,Y,F)) compose to be functional in two of its modes. (4) (8N 8N0 8Y 8Y0 8Y00 8F) ((compose(N,Y,F)$ compose(N0,Y0,F)) (compose(Y00,Y0,Y) ^ compose(N,Y00,N0))) compose to be associative. This new path exploration relation path/1 is de ned by Program B1 path(Y) atomic(Y) path(Y) compose(Y00, Y0, Y) , atomic(Y00) , path(Y0) Program B2 path(Y) atomic(Y) path(Y) compose(Y00, Y0, Y) , atomic(Y0) , path(Y00) We should note that all the four path searching programs above act as interpreters for programs de ned by the lts/1 relation. 9 Program Derivation by Partial Evaluation Programs A1, A2, B1 and B2 can be used as general templates to describe a class of programs which incrementally instantiate observable variables during the course of their execution; speci c instances of programs are determined by the de nition of atomic/1, determined by lts/1. We have coded the relations for compose/3, atomic/1 and both path/1 and path/2 in SICStus 14 Prolog in order to explore the possibilities of transforming the generic path programs into specialised forms for given LTS's. A design decision was taken early on to distinguish between meta-level and object-level variables in the Prolog code by using the ground term representation, in order to preserve the semantics of the de nitions. We then use partial evaluation in order to produce a program which incorporates the path searching interpreter and our compose/3 relation with a speci c labelled transition system as de ned by lts/1. Partial evaluation of logic programs is an optimisation technique which has been described in logic programming terms by Lloyd and Shepherdson [15] as follows: \Given a program P and a goal G, partial evaluation produces a new program P 0 which is P `specialised' to the goal G. The intention is that G should have the same (correct and computed) answers w.r.t. P and P 0, and that G should run more e ciently for P 0 than for P". Both folding and unfolding are techniques used in partial evaluation: logical folding is the replacement of a goal that is an instance of the body of a clause by the corresponding instance of the head of the clause; logical unfolding of the goal Xi in the clause H X1; : : : ; Xi 1; Xi; Xi+1; : : : ; Xn where Xi is de ned by X B1; : : : ; Bm is de ned by the following transformation: f(H X1; : : : ; Xi 1; B1; : : : ; Bm; Xi+1; : : : ; Xn) j mgu(X;Xi)^ 6= falseg Although partial evaluation can be done by hand, we have used Mixtus [21], the excellent partial evaluator for Prolog developed by Dan Sahlin, and have obtained good initial results. The choice of Prolog permits the simpli cation of the relationship between the data structures used, the meta-interpreter of the substitutionchanging relation, and the resulting synthesized code. This is because the same language is used to represent the observables, the program in the LTS language and the interpreter based on graph searching. The methodology itself is nonetheless applicable to any implementation language, but the amount of code actually needed may be signi cantly greater. In the case of an implementation in logic programming, the method naturally does not provide any universal mechanism for synthesizing arbitrary 15 logic programs. By the nature of the initial assumptions chosen, only programs whose state changes result in bindings to variables in an initial query are expressible by this method. On the general level of process description this corresponds to systems whose change of state is always visible to the outside environment, e.g. via observable communication between processes. 10 Comparison with other work The algebraic structure of atomic formulae, including the lattice properties of the instantiation order relation, were described independently in the early seventies by Reynolds [18] and Plotkin [16]. Both authors were also interested in mechanical theorem proving. Reynolds showed in his paper that the refutation of \transformational systems" (sets of clauses containing only unit clauses and clauses with one positive and one negative literal) was in e ect path searching, but that there was no decision procedure for such systems. Plotkin discussed the use of induction to nd least generalizations of clauses or literals and showed that there is an algorithm to nd the least generalization of any pair of literals or terms. It is interesting to note that in his paper Plotkin considered the possibilities of automated induction; the path searching algorithms described in our work relate to induction, but it is not our goal to try to enhance the speci cation by generalisation. Belia and Occhiuto [2] have developed an explicit calculus of substitutions which extends Reynold's gci [18] and combines Robinson's uni cation [19] and term instances. Their work aims to avoid the drawback of the gap between the theory and current implementations of logic programming languages represented by the use of metalevel structures, like substitutions, and mechanisms, like mgu and instantiation, to deal with the substitution rule. Their calculus of c-expressions permits structures to be dealt with explicitly at the object level which would otherwise typically be hidden at the metalevel. They put the substitution rule as an additional operator, mgi, of the language of terms, and provide c-expressions as programs. We prefer to work initially at the metalevel, and to take a classical approach based on interpretation [13, Chapter 12] and partial evaluation (see for example [15, 3]). C-expressions which use integers as tuple indexes do not exploit the tree structure of terms; Belia and Occhiuto are investigating a di erent calculus using paths instead of integers, which may be closer to our approach. The language of Associons [17] was developed by Martin Rem as a pro16 gram notation without variables; the motivation was to develop a language model which employed more concurrency than traditional languages based on assignment. An associon is a tuple of names de ning a relation between entities represented by these names. The state of a computation can be changed by a forward chaining process based on the \closure statement", which creates new associons that represent new relations deduced from the already existing ones. The language of associons is essentially deterministic and is based on sets. In fact the language does have logical variables and also universal quanti ers over closure statements. These statements are effectively normal program clauses (i.e. they can contain negated conditions) [14], and also contain guards. Our programs are expressed as de nite program clauses, without negated conditions, and in contrast to Rem's language our approach is based on the backward-chaining principle of logic programming and permits the expression of all-solutions non-determinism since our language does not contain guards. A similarity between our approach and that of Rem is that both formalisms permit the construction of programs which are inherently concurrent. Banâtre and Le M etayer have developed the Gamma language [1] which also permits the construction of programs which are inherently parallel in their operation. A Gamma program is essentially a multiset transformer operating on all the data at once; it `reacts' on multisets of data by replacing a subset whose elements satisfy a given property by the result of the application of a function on that subset. Gamma is an intermediate language between speci cations in rst order logic and traditional programming languages; programs in Gamma describe the logic of an algorithm and are transformed into executable programs by expressing lower-level choice such as data representation and execution order. Central to the Gamma language is non-determinism, expressed as the choice between several subsets which are candidates for reaction, and the locality principle, which permits independent and simultaneous reactions on disjoint subsets. The multiset is seen as a representation of the state of a system in Gamma; although our approach is based on sets rather than multisets, there is a similarity in that the set of bindings is regarded as the state of the system. There is no recursive data structure de nition in Gamma, and data has to be represented as at multisets of items; for example trees are represented by nodes and leaves associated with parenthood information. We preserve the tree structure of terms due to our use of term substitution, but do employ types to indicate the position of subterms within a term. In both Gamma and our formalism this means that all components of a data structure are directly accessible, 17 independently of their position in the structure. However, in contrast withGamma, our technique does not have direct equivalents to the operations ofdata expansion and data reduction.The work of Gilbert and Hogger [8, 9] described the instantiation of agiven term X by a given substitution Y to give a new term Z by a relationsubst(X,Y,Z) where any substitution Y was constructed by applying a tupling<> to some set fY1; : : : ; Yng of simpler substitutions. Y was representedby means of a substitution-tree, and a special symbol used exclusivelyto describe variables. A major drawback of this method is that it wasonly applicable systems which generated lists, since the non-inclusion of S-trees in the Herbrand universe required the transformation of the subst/3relation into one which does operate over Herbrand terms, but which is notassociative.Our work is closely related to the area of partial evaluation, in particularas applied to logic programs. Work in this eld has been carried out byLloyd et al. [15, 3] amongst others, who have given a strong theoreticalfoundation for partial evaluation in logic programming, and Dan Sahlin,who has constructed a robust partial evaluator for Prolog [20, 21]. Partialevaluation for concurrent logic languages has been explored by Fujita et al.[6] for GHC programs, and by Huntbach [12] for Parlog programs.Furthermore, our method based on a graph traversal template can beregarded as an interpreter for graph-based computations, and in this senseis related to the work by Gallier et al. [7] on graph-based interpreters forgeneral Horn clauses.11 ConclusionsThe work reported in this paper reconstructs the method of Gilbert andHogger for deriving logic programs from the expected observations of pro-gram behaviour. We replace their concept of substitution trees (S-trees) bybinding sets, and show that a more general method can be developed basedon substitution mappings as the basis for the theory. We have formulatedpath exploration programs which act as generalised program schemata forcertain classes of systems, and have derived specialised instances of theseprograms by partial evaluation of the schemata and speci cations of pro-gram behaviour given in terms of labelled transition systems. The partialevaluation stage has been successfully mechanised using Mixtus [21], a par-tial evaluator for Prolog.18 AcknowledgementsThis work was partially supported by PECO Fellowship grants CT931675(David Gilbert) and CT926844 (Ji r Zlatu ska) provided by the EuropeanCommunity under the scheme for Scienti c and Technical Cooperation withCentral and Eastern Europe.References[1] J-P. Banâtre and D. Le M etayer. Programming by Multiset Transfor-mation. Communications of the ACM, 36(1):98{111, 1993.[2] M. Belia and M. E. Occhiuto. C-expressions: a variable{free calculus forequational logic programming. Theoretical Computer Science, 107:209{252, 1993.[3] K. Benkerimi and J. W. Lloyd. A partial evaluation procedure for logicprograms. In Debray and Hermenegildo [5], pages 343{358.[4] D. R. Brough and C. J. Hogger. Compiling associativity into logicprograms. The Journal of Logic Programming, 4(4):345{360, December1987.[5] S. Debray and M. Hermenegildo, editors. Proceedings of the 1990 NorthAmerican Conference on Logic Programming, Austin, 1990. ALP, MITPress.[6] H. Fujita, A. Okumura, and K. Furukawa. Partial evaluation of GHCprograms based on the UR-set with constraints. In R. A. Kowalski andK. A. Bowen, editors, Proceedings of the Fifth International Conferenceand Symposium on Logic Programming, pages 924{941, Seatle, 1988.ALP, IEEE, The MIT Press.[7] J. H. Gallier and S. Raatz. Hornlog: A graph-based interpreter forgeneral Horn clauses. The Journal of Logic Programming, 4(2):119{156, June 1987.[8] D. R. Gilbert and C. J. Hogger. Logic for representing and implement-ing knowledge about system behaviour. In V Ma r k, O St epankova,and R Trappl, editors, Proceedings of the International Summer Schoolon Advanced Topics in Arti cial Intelligence, pages 42{49, Prague, Jul1992. Springer Verlag Lecture Notes in Arti cial Intelligence No. 617.19 [9] D. R. Gilbert and C. J. Hogger. Deriving logic programs from obser-vations. In Jean-Marie Jacquet, editor, Constructing Logic Programs.John Wiley, 1993.[10] P. M. Hill and J. W. Lloyd. Analysis of Meta-programs. Technical Re-port CS-88-08, Department of Computer Science, University of Bristol,Bristol, UK, June 1988.[11] P. M. Hill and J. W. Lloyd. The Godel programming language. MITPress, 1993.[12] M. Huntbach. Meta-interpreters and partial evaluation in parlog. For-mal Aspects of Computing, 1(2):193{211, 1989.[13] R. A. Kowalski. Logic for problem solving. North Holland, 1979.[14] J. W. Lloyd. Foundations of Logic Programming. Spinger-Verlag,Berlin, second edition, 1987.[15] J. W. Lloyd and J. C. Sheperdson. Partial evaluation in logic pro-gramming. The Journal of Logic Programming, 11(3 & 4):217{242,October/November 1991.[16] G. D. Plotkin. A note on inductive generalization. In B. Meltzer andD. Mitchie, editors, Machine Intelligence, pages 153{165, 1970.[17] M. Rem. Associons: A Program Notation with Tuples instead of Vari-ables. ACM Transactions on Programming Languages and Systems,3(3):251{262, Jul 1981.[18] J. C. Reynolds. Transformational systems and the algebraic structureof atomic formulas. In B. Meltzer and D. Mitchie, editors, MachineIntelligence, pages 135{151, 1970.[19] J. A. Robinson. A machine-orientated logic based on the resolutionprinciple. Journal of the ACM, 12(1):23 { 49, Jan 1965.[20] D. Sahlin. The mixtus approach to automatic partial evaluation of fullProlog. In Debray and Hermenegildo [5], pages 377{398.[21] D. Sahlin. An Automatic Partial Evaluator for Full Prolog. PhD thesis,Swedish Institute of Computer Science, Mar 1991.20

برای دانلود متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

منابع مشابه

Transforming Speci cations of ObservableBehaviour into

A methodology for deriving programs from speciications of observable behaviour is described. The class of processes to which this methodology is applicable includes those whose state changes are fully deenable by labelled transition systems, for example communicating processes without internal state changes. A logic program representation of such labelled transition systems is proposed, interpr...

متن کامل

Relative Specification and Transformational Re-Use of Functional Programs

A relative speciication is a collection of laws relating the behaviour of a required new program to that of one or more existing programs. A two stage method for transforming such relative speciications into eeective functional programs is described and illustrated. The inversion stage rearranges the specifying laws to obtain a collection of partial deenitions for each unknown function, typical...

متن کامل

Transforming Specifications of Observable Behaviour into Programs

A methodology for deriving programs from specifications of observable behaviour is described. The class of processes to which this methodology is applicable includes those whose state changes are fully definable by labelled transition systems, for example communicating processes without internal state changes. A logic program representation of such labelled transition systems is proposed, inter...

متن کامل

Data Reening Logic Programs

A reenement calculus provides a method for transforming speciications to executable code, maintaining the correctness of the code with respect to its speciication. One aspect of reenement is transforming the representation of data in a speciication. This could be performed for eeciency reasons, or to change an abstract speciication type into a data type that is in the target implementation lang...

متن کامل

An Automatic Trace Analysis

This paper describes the development of Tango, an automatic generator of backtracking trace analysis tools for single-process speciications written in the formal description language , Estelle. A tool generated by Tango automatically checks the validity of any execution trace against the given speciication, and supports a number of checking options. The approach taken was to modify an Estelle-t...

متن کامل

Modular Specification of Concurrent Systems with Observational Logic

We present a dynamic form of observational logic for specifying concurrent systems on the basis of their observable behaviour, in particular without needing a language for describing states, which are regarded as non-observable. The logic is based on quantales. The models are labelled transition systems, and a weakly complete proof system is presented. We study the logic from the point of view ...

متن کامل

ذخیره در منابع من


  با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید

برای دانلود متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید

ثبت نام

اگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید

عنوان ژورنال:

دوره   شماره 

صفحات  -

تاریخ انتشار 1994